using System;
using System.Collections;
using Newtonsoft.Json;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;

namespace WorkFlow.Net.Process
{
    public class AccountInfo : MonoBehaviour
    {
#if UNITY_EDITOR && ACCOUNT_INFO_AUTO_START
        [SerializeField] [BoxGroup("Editor")] private string dataTail;
#endif
        
#if HISTORY_INFO
         [SerializeField] private bool needPlayTimesHistory;
#endif
        public static AccountInfo Instance { get; private set; }

        public System.Func<string> OnDomainAddress { get; set; }

        [SerializeField] private UnityEvent<string,System.Action> onNetError = new UnityEvent<string,System.Action>();
        [SerializeField] private UnityEvent onLoginSet = new UnityEvent();
        public UnityEvent OnLoginSet => onLoginSet;
        public UnityEvent<string, System.Action> OnNetError => onNetError;
        public string ReportAddress { get; private set; }
        public string TreasureChestId { get; private set; }
        public string DataTail { get; private set; }
        public string ExternGameTagStr { get; private set; }

#if REMOTE_INFO
        public string NickName { get; private set; }
        public string TenantUserId { get; private set; }
        [Obsolete("use TenantUserId")]
        public string UserId { get; private set; }
        public string Avatar { get; private set; }
        public int Sex { get; private set; }
        private bool RemoteInfoReady { get; set; }

        public bool AvatarReady { get; set; }
        public Texture AvatarTex { get; private set; }
        public Sprite AvatarSprite { get; private set; }

        public event System.Action OnAvatarReady;
#endif

#if HISTORY_INFO
        public int TodayTime { get; private set; }
        public int TotalTime { get; private set; }
        public int TotalNumber { get; private set; }
        private bool HistoryInfoReady { get; set; }
#endif

        private void Awake()
        {
            if (Instance != null && Instance != this)
            {
                Destroy(gameObject);
                return;
            }
            Instance = this;
        }

#if UNITY_EDITOR && ACCOUNT_INFO_AUTO_START
        private void Start()
        {
            SetDataTail(dataTail);
            SetCompleted();
        }
#endif

        private void SetTreasureChestId(string treasureChestId)
        {
            TreasureChestId = treasureChestId;
        }

        private void SetDataTail(string inputDataTail)
        {
            DataTail = inputDataTail;
        }

        private void SetReportAddress(string reportAddress)
        {
            ReportAddress = reportAddress;
        }

        private void SetGameTag(string gameTag)
        {
            ExternGameTagStr = gameTag;
        }
        
        private void SetCompleted()
        {
            if (NetPlayerPresData.Instance == null)
            {
                NetPlayerPresData.LoadData(DataTail);
            }
            if(OnDomainAddress!=null)
                NetPlayerPresData.Instance.Address = OnDomainAddress?.Invoke();
            if (!string.IsNullOrEmpty(ExternGameTagStr))
            {
                if (Enum.TryParse(ExternGameTagStr, out GameTagEnum gameTag))
                {
                    NetPlayerPresData.Instance.GameTag = gameTag;
                }
                else
                {
                    Debug.LogError($"Parse GameTag Error : {ExternGameTagStr}" );
                }
            }
#if UNITY_EDITOR && ACCOUNT_INFO_AUTO_START
            SetTreasureChestId(NetPlayerPresData.Instance.TreasureChestId);
#endif
            
#if REMOTE_INFO
            StartCoroutine(GetUrl(NetPlayerPresData.Instance.UserDetailUrl, NetPlayerPresData.Instance.Token, LoadRemoteInfoEnd));
#endif
            
#if HISTORY_INFO
            if(needPlayTimesHistory){
                StartCoroutine(GetUrl(NetPlayerPresData.Instance.HistoryUrl, NetPlayerPresData.Instance.Token, LoadHistoryInfoEnd));
            }
#endif

#if !REMOTE_INFO && !HISTORY_INFO
             onLoginSet?.Invoke();
#endif
        }

#if REMOTE_INFO
        void LoadRemoteInfoEnd(string responseStr)
        {
            Debug.Log(responseStr);
            RemoteDataRoot remoteDataRoot = null;
            try
            {
                remoteDataRoot = JsonConvert.DeserializeObject<RemoteDataRoot>(responseStr);
            }
            catch (Exception e)
            {
                remoteDataRoot = RemoteDataRoot.Default;
            }
            if (remoteDataRoot.Code != 200)
            {
                Debug.Log( NetPlayerPresData.Instance.Token);
                OnNetError?.Invoke(remoteDataRoot.Msg, () =>
                {
                    StartCoroutine(GetUrl(NetPlayerPresData.Instance.UserDetailUrl, NetPlayerPresData.Instance.Token, LoadRemoteInfoEnd));
                });
                return;
            }
            UserDetail userDetail = remoteDataRoot.Data.ToObject<UserDetail>();
            if (userDetail != null)
            {
                NickName = userDetail.TenantUser.UserInfo.NickName;
                TenantUserId = userDetail.TenantUser.UserInfo.TenantUserId;
                UserId = userDetail.TenantUser.UserInfo.UserId;
                Avatar = userDetail.TenantUser.UserInfo.Avatar;
                Sex = userDetail.TenantUser.UserInfo.Sex;
                RemoteInfoReady = true;
                StartCoroutine(LoadRemoteAvatar());
#if HISTORY_INFO
                if(HistoryInfoReady || !needPlayTimesHistory)
                    onLoginSet?.Invoke();
#else
                onLoginSet?.Invoke();
#endif
            }
            else
            {
                throw new Exception("Response is null");
            }
        }
#endif

        IEnumerator LoadRemoteAvatar()
        {
#if REMOTE_INFO
            AvatarReady = false;
            if (!string.IsNullOrEmpty(Avatar))
            {
                Debug.Log(Avatar);
                using UnityWebRequest request = UnityWebRequest.Get(Avatar);
                var downloadHandlerTexture = new DownloadHandlerTexture();
                request.downloadHandler = downloadHandlerTexture;
                yield return request.SendWebRequest();
                AvatarReady = true;
                if (string.IsNullOrEmpty(request.error))
                {
                    AvatarTex = downloadHandlerTexture.texture;
                    AvatarSprite = Sprite.Create((Texture2D)AvatarTex, new Rect(0, 0, AvatarTex.width, AvatarTex.height), Vector2.zero);
                    OnAvatarReady?.Invoke();
                }
            }
            else
            {
                AvatarReady = true;
            }
#else
            yield break;
#endif
        }

#if HISTORY_INFO
        void LoadHistoryInfoEnd(string responseStr)
        {
            Debug.Log(responseStr);
            RemoteDataRoot remoteDataRoot = null;
            try
            {
                remoteDataRoot = JsonConvert.DeserializeObject<RemoteDataRoot>(responseStr);
            }
            catch (Exception e)
            {
                remoteDataRoot = RemoteDataRoot.Default;
            }
            if (remoteDataRoot.Code != 200)
            {
                Debug.Log( NetPlayerPresData.Instance.Token);
                OnNetError?.Invoke(remoteDataRoot.Msg, () =>
                {
                    StartCoroutine(GetUrl(NetPlayerPresData.Instance.HistoryUrl, NetPlayerPresData.Instance.Token, LoadHistoryInfoEnd));
                });
                return;
            }
            HistoryData historyData = remoteDataRoot.Data.ToObject<HistoryData>();
            if (historyData != null)
            {
                TodayTime = historyData.TodayTime;
                TotalTime = historyData.TotalTime;
                TotalNumber = historyData.TotalNumber;
                HistoryInfoReady = true;
#if REMOTE_INFO
                if(RemoteInfoReady)
                    onLoginSet?.Invoke();
#else
                onLoginSet?.Invoke();
#endif
            }
            else
            {
                throw new Exception("Response is null");
            }
        }
#endif

        private IEnumerator GetUrl(string url, string token,System.Action<string> callBack)
        {
            Debug.Log("Account Info : " + url);
            using UnityWebRequest request = new UnityWebRequest(url, UnityWebRequest.kHttpVerbGET);
            try
            {
                request.downloadHandler = new DownloadHandlerBuffer();
                request.SetRequestHeader("Authorization", $"Bearer {token}");
                request.SetRequestHeader("xySource", "CLIENT");
                yield return request.SendWebRequest();
                if (request.result == UnityWebRequest.Result.Success)
                {
                    Debug.Log($"{url} -> Response: " + request.downloadHandler.text);
                    try
                    {
                        callBack?.Invoke(request.downloadHandler.text);
                    }
                    catch (Exception e)
                    {
                        callBack?.Invoke(null);
                        Console.WriteLine(e);
                    }
                }
                else
                {
                    Debug.LogError($"{url} -> Error: " + request.error + "  : " + url +"      \nToken: " + token);

                    Instance.OnNetError?.Invoke(request.error, () =>
                    {
                        StartCoroutine(GetUrl(url, token, callBack));
                    });
                }
            }
            finally
            {
                request.Dispose();
            }
        }

        private void OnDestroy()
        {
            if (Instance == this)
            {
                Instance = null;
            }
        }
    }
}

